package com.sh.data.engine.domain.dataquality.service.impl;

import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.sh.data.engine.common.enumDefinition.DataQualityRuleCompareTypeEnum;
import com.sh.data.engine.domain.base.model.PageResult;
import com.sh.data.engine.domain.dataasset.service.TableService;
import com.sh.data.engine.domain.dataquality.model.domain.DataQualityJobDomain;
import com.sh.data.engine.domain.dataquality.model.domain.DataQualityJobRuleDetailDomain;
import com.sh.data.engine.domain.dataquality.model.domain.DataqualityJobMonitorDomain;
import com.sh.data.engine.domain.dataquality.model.param.DataQualityTaskParam;
import com.sh.data.engine.domain.dataquality.service.DataQualityJobRuleFieldService;
import com.sh.data.engine.domain.dataquality.service.DataQualityJobRuleService;
import com.sh.data.engine.domain.dataquality.service.DataQualityJobService;
import com.sh.data.engine.domain.shims.db.model.TableInfoDomain;
import com.sh.data.engine.repository.dao.dataquality.DataQualityJobMapper;
import com.sh.data.engine.repository.dao.dataquality.entity.DataQualityJobEntity;
import com.sh.data.engine.repository.dao.dataquality.entity.DataQualityJobRuleEntity;
import com.sh.data.engine.repository.dao.dataquality.entity.DataQualityJobRuleFieldEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author tinglan.ys
 * @description:
 * @date 2022/2/15 下午6:10
 */
@Service
@Slf4j
public class DataQualityJobServiceImpl
    extends ServiceImpl<DataQualityJobMapper, DataQualityJobEntity>
    implements DataQualityJobService {

    @Autowired
    private DataQualityJobRuleService dataqualityJobRuleService;

    @Autowired
    private DataQualityJobRuleFieldService dataqualityJobRuleFieldService;

    @Autowired
    private TableService tableService;

    /**
     * @param request
     * @param projectId
     * @description : 获取任务列表
     * @author : tinglan.ys
     * @date : 2022/2/18
     */
    @Override
    public IPage<DataQualityJobDomain> getJobs(DataQualityTaskParam request, Long projectId) {

        String tblName = request.getTblName();
        Integer cycle = request.getCycle();
        Integer jobStatus = request.getJobStatus();

        // 排序和排序字段暂时不实现这个功能

        String orderField = request.getOrderField();
        String order = request.getOrder();
        LambdaQueryWrapper<DataQualityJobEntity> lambdaQueryWrapper = new LambdaQueryWrapper<DataQualityJobEntity>()
            // .eq(DataQualityJobEntity::getIsLast, 1)    //原来只展示某个表的最新的一条任务,现在便于查看把这个逻辑去了先
            .eq(DataQualityJobEntity::getProjectId, projectId)
            .like(StringUtils.isNotBlank(tblName), DataQualityJobEntity::getTblName, tblName)
            .eq(cycle != null, DataQualityJobEntity::getTaskCycle, cycle)
            .eq(jobStatus != null, DataQualityJobEntity::getStatus, jobStatus)
            .orderByDesc(DataQualityJobEntity::getCreateTime);

        IPage<DataQualityJobDomain> convert = this.page(
                new Page<>(request.getPageNum(), request.getPageSize()), lambdaQueryWrapper)
            .convert(e -> Convert.convert(DataQualityJobDomain.class, e));


//    List<DataQualityJobEntity> jobs =
//        this.list(
//            new LambdaQueryWrapper<DataQualityJobEntity>()
//                // .eq(DataQualityJobEntity::getIsLast, 1)    //原来只展示某个表的最新的一条任务,现在便于查看把这个逻辑去了先
//                .eq(DataQualityJobEntity::getProjectId, projectId)
//                .like(StringUtils.isNotBlank(tblName), DataQualityJobEntity::getTblName, tblName)
//                .eq(cycle != null, DataQualityJobEntity::getTaskCycle, cycle)
//                .eq(jobStatus != null, DataQualityJobEntity::getStatus, jobStatus)
//                .orderByDesc(DataQualityJobEntity::getCreateTime));

//    List<DataQualityJobDomain> dataQualityJobDomains =
//        ConvertUtil.copyProperties(jobs, DataQualityJobDomain.class);
        List<DataQualityJobDomain> dataQualityJobDomains = convert.getRecords();
        for (DataQualityJobDomain dataQualityJobDomain : dataQualityJobDomains) {
            // 需要封装该表的 是否是分区表信息
            TableInfoDomain tableInfo =
                tableService.getTableInfo(projectId, dataQualityJobDomain.getTblName());
            if (tableInfo != null) {
                dataQualityJobDomain.setHasPartition(tableInfo.isPartitionTable() ? 1 : 0);
            }
        }
        return convert;
    }

    /**
     * @param jobId
     * @param pageNum
     * @param pageSize
     * @description : 获取任务规则详情
     * @author : tinglan.ys
     * @date : 2022/2/18
     */
    @Override
    public PageResult<DataQualityJobRuleDetailDomain> getJobRuleDetails(
        Long jobId, Integer pageNum, Integer pageSize) {

    /*  SELECT
    jr.*,
            r.field_names
    FROM
    dataquality_job_rule jr
    LEFT JOIN dataquality_rule r ON jr.rule_id = r.id
    WHERE
    jr.dataquality_job_id = #{jobId}
    ORDER BY
    r.create_time*/

        List<DataQualityJobRuleEntity> ruleDetails =
            dataqualityJobRuleService.list(
                new LambdaQueryWrapper<DataQualityJobRuleEntity>()
                    .eq(DataQualityJobRuleEntity::getDataqualityJobId, jobId)
                    .orderByDesc(DataQualityJobRuleEntity::getCreateTime));

        List<DataQualityJobRuleDetailDomain> responses = new ArrayList<>();

        if (CollectionUtils.isNotEmpty(ruleDetails)) {
            for (DataQualityJobRuleEntity detail : ruleDetails) {
                DataQualityJobRuleDetailDomain response = new DataQualityJobRuleDetailDomain();
                BeanUtils.copyProperties(detail, response);

                List<DataQualityJobRuleFieldEntity> fields =
                    dataqualityJobRuleFieldService.list(
                        new LambdaQueryWrapper<DataQualityJobRuleFieldEntity>()
                            .eq(DataQualityJobRuleFieldEntity::getDataqualityJobRuleId, detail.getId())
                            .in(DataQualityJobRuleFieldEntity::getStatus, Lists.newArrayList(2, 3)));

                response.setFields(fields);
                responses.add(response);
            }
        }

        PageResult<DataQualityJobRuleDetailDomain> pageResult =
            new PageResult<>(responses, pageNum, pageSize);
        return pageResult;
    }

    /**
     * @param jobId
     * @param pageNum
     * @param pageSize
     * @description : 获取任务规则所有字段详情-监控结果列表页
     * @author : tinglan.ys
     * @date : 2022/2/18
     */
    @Override
    public DataqualityJobMonitorDomain getJobRuleFields(
        Long jobId, Integer pageNum, Integer pageSize) {

        DataQualityJobEntity dataqualityJob = this.getById(jobId);

        DataqualityJobMonitorDomain dataqualityJobMonitorDomain = new DataqualityJobMonitorDomain();
        dataqualityJobMonitorDomain.setTableName(dataqualityJob.getTblName());

        List<DataQualityJobRuleEntity> jobRules =
            dataqualityJobRuleService.list(
                new LambdaQueryWrapper<DataQualityJobRuleEntity>()
                    .eq(DataQualityJobRuleEntity::getDataqualityJobId, jobId));

        List<DataqualityJobMonitorDomain.DataqualityJobRuleFieldExt> exts = new ArrayList<>();

        PageResult<DataqualityJobMonitorDomain.DataqualityJobRuleFieldExt> pageResult =
            new PageResult<>(exts, pageNum, pageSize);

        if (CollectionUtils.isNotEmpty(jobRules)) {
            List<Long> jobRuleIds = jobRules.stream().map(jr -> jr.getId()).collect(Collectors.toList());

            List<DataQualityJobRuleFieldEntity> ruleFields =
                dataqualityJobRuleFieldService.list(
                    new LambdaQueryWrapper<DataQualityJobRuleFieldEntity>()
                        .in(DataQualityJobRuleFieldEntity::getDataqualityJobRuleId, jobRuleIds));

            for (DataQualityJobRuleFieldEntity ruleField : ruleFields) {
                DataqualityJobMonitorDomain.DataqualityJobRuleFieldExt ext =
                    new DataqualityJobMonitorDomain.DataqualityJobRuleFieldExt();
                BeanUtils.copyProperties(ruleField, ext);

                DataQualityJobRuleEntity dataqualityJobRule =
                    jobRules.stream()
                        .filter(jr -> Objects.equals(jr.getId(), ruleField.getDataqualityJobRuleId()))
                        .findFirst()
                        .get();

                List<String> compareTypeList = new ArrayList<>();
                if (dataqualityJobRule.getRuleCompareType() != null) {
                    String[] ruleCompareTypeList = dataqualityJobRule.getRuleCompareType().split(",");
                    for (String ruleCompareType : ruleCompareTypeList) {
                        DataQualityRuleCompareTypeEnum compareType =
                            DataQualityRuleCompareTypeEnum.getByCompareType(Integer.valueOf(ruleCompareType));
                        compareTypeList.add(compareType == null ? null : compareType.getDesc());
                    }
                }

                ext.setCompareType(StringUtils.join(compareTypeList, ","));
                ext.setExpectValue(dataqualityJobRule.getRuleExpectValue());
                ext.setRuleForm(dataqualityJobRule.getRuleFrom());
                ext.setRuleName(dataqualityJobRule.getRuleName());
                exts.add(ext);
            }

            pageResult = new PageResult<>(exts, pageNum, pageSize);
        }
        dataqualityJobMonitorDomain.setPageInfo(pageResult);

        return dataqualityJobMonitorDomain;
    }
}
